#!/bin/bash
# This test reboots a lot, generates container images, etc.
# kola: { "timeoutMin": 30 }
#
# Copyright (C) 2021 Red Hat, Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.

set -euo pipefail

. ${KOLA_EXT_DATA}/libtest.sh

set -x

libtest_prepare_offline
cd $(mktemp -d)

# TODO: It'd be much better to test this via a registry
image_dir=/var/tmp/fcos
image=oci:$image_dir
image_pull=ostree-unverified-image:$image
tmp_imagedir=/var/tmp/fcos-tmp
arch=$(arch)

case "${AUTOPKGTEST_REBOOT_MARK:-}" in
  "")
    # Take the existing ostree commit, and export it to a container image, then rebase to it.

    checksum=$(rpm-ostree status --json | jq -r '.deployments[0].checksum')
    v0=$(rpm-ostree status --json | jq -r '.deployments[0].version')
    rm ${image_dir} -rf
    
    # Since we're switching OS update stream, turn off zincati
    systemctl mask --now zincati

    ostree container encapsulate --repo=/ostree/repo ${checksum} "${image}"
    # This one keeps --experimental, but we also test without it below
    rpm-ostree rebase --experimental "$image_pull" | tee out.txt
    assert_file_has_content out.txt 'Importing.*'"$image_pull"
    rpmostree_assert_status ".deployments[0][\"container-image-reference\"] == \"ostree-unverified-image:$image\""
    # Verify we use the merge commit now
    rpmostree_assert_status ".deployments[0][\"checksum\"] != \"${checksum}\""
    echo "ok rebase to container image reference"

    rpm-ostree status | tee out.txt
    assert_file_has_content_literal out.txt 'Digest: sha256:'
    ostree container image list --repo=/ostree/repo | tee imglist.txt
    assert_streq "$(wc -l < imglist.txt)" 1

    v1=$(rpm-ostree status --json | jq -r '.deployments[0].version')
    assert_streq "${v0}" "${v1}"

    # Test rebasing back to ostree https://github.com/coreos/rpm-ostree/issues/3677
    rpm-ostree rebase "$checksum"
    rpm-ostree rebase "$image_pull"

    /tmp/autopkgtest-reboot 1
    ;;
  1)
    # Some tests of other things

    if rpm-ostree deploy 42 2>err.txt; then
        fatal "unexpectedly deployed version from container image reference"
    fi
    assert_file_has_content err.txt 'Cannot look up version while tracking a container image reference'
    echo "ok cannot deploy when tracking container image"

    # Test layering
    if rpm -q foo 2>/dev/null; then
      fatal "found foo"
    fi
    rpm-ostree install ${KOLA_EXT_DATA}/rpm-repos/0/packages/x86_64/foo-1.2-3.x86_64.rpm
    echo "ok layering package"

    # Test no-op upgrade
    rpm-ostree upgrade | tee out.txt
    assert_file_has_content_literal out.txt "Pulling manifest: ${image_pull}"
    assert_file_has_content out.txt "No upgrade available."
    echo "ok no upgrade available"

    # Now, copy the OCI dir to containers-storage for a local build
    skopeo copy $image containers-storage:localhost/fcos
    rm "${image_dir}" -rf
    td=$(mktemp -d)
    cd ${td}
    arch=$(arch)
    # TODO close race here around webserver readiness
    (cd ${KOLA_EXT_DATA}/rpm-repos/0 && ~core/kolet httpd) &
    while ! curl -q http://127.0.0.1; do sleep 1; done
    cat >local.repo << 'EOF'
[local]
gpgcheck=0
baseurl=http://127.0.0.1
EOF
    cat >baz.yaml << 'EOF'
packages:
  - baz-1.0
  - boo-1.0
EOF
    cat >testdaemon-query.yaml << 'EOF'
repo-packages:
  - repo: local
    packages:
      - testdaemon
EOF
    cat >nonano.yaml << 'EOF'
override-remove:
  - nano
  - nano-default-editor
EOF
    cp ${KOLA_EXT_DATA}/rpm-repos/0/packages/x86_64/baz-2.0-1.x86_64.rpm .
    baz_chksum=$(sha256sum baz-2.0-1.x86_64.rpm | cut -f1 -d' ')
    cat >replace-baz.yaml <<EOF
override-replace-local:
  baz-2.0-1.x86_64: ${baz_chksum}
ex-override-replace:
  - from:
      repo: local
    packages:
      - boo
EOF
cat > Dockerfile << EOF
FROM localhost/fcos
RUN rm -rf /etc/yum.repos.d/*  # Ensure we work offline
ADD local.repo /etc/yum.repos.d/
RUN rpm-ostree install bar
RUN mkdir -p /etc/rpm-ostree/origin.d
ADD baz.yaml testdaemon-query.yaml nonano.yaml /etc/rpm-ostree/origin.d/
RUN rpm-ostree ex rebuild
ADD replace-baz.yaml /etc/rpm-ostree/origin.d/
ADD baz-2.0-1.x86_64.rpm /run/rpm-ostree/staged-rpms/${baz_chksum}.rpm
RUN rpm-ostree ex rebuild
RUN echo some config file > /etc/someconfig.conf
RUN echo somedata > /usr/share/somenewdata
# Verify we're ignoring subdirectories that don't contain vmlinuz https://github.com/coreos/rpm-ostree/issues/3965
RUN mkdir -p /usr/lib/modules/blah && touch /usr/lib/modules/blah/foo
RUN rpm-ostree cleanup -m
EOF
    # Older podman found in RHEL8 blows up without /etc/resolv.conf
    # which happens in our qemu path.
    touched_resolv_conf=0
    if test '!' -f /etc/resolv.conf; then
      podmanv=$(podman --version)
      case "${podmanv#podman version }" in
        3.*) touched_resolv_conf=1; touch /etc/resolv.conf;;
      esac
    fi
    podman build --net=host -t localhost/fcos-derived --squash .
    if test "${touched_resolv_conf}" -eq 1; then
      rm -vf /etc/resolv.conf
    fi
    rpm-ostree rebase ostree-unverified-image:containers-storage:localhost/fcos-derived
    ostree container image list --repo=/ostree/repo | tee imglist.txt
    # We now only prune when the deployment is removed
    assert_streq "$(wc -l < imglist.txt)" 2
    rm $image_dir -rf
    /tmp/autopkgtest-reboot 3
    ;;
  3) 
    rpm -q foo
    grep -qF 'some config file' /etc/someconfig.conf || (echo missing someconfig.conf; exit 1)
    grep -qF somedata /usr/share/somenewdata || (echo missing somenewdata; exit 1)
    for p in bar testdaemon; do
      assert_streq $(rpm -q $p) $p-1.0-1.${arch}
      test -f /usr/bin/$p
    done
    assert_streq $(rpm -q baz) baz-2.0-1.${arch}
    test -f /usr/bin/baz
    ! rpm -q nano
    rpmostree_assert_status ".deployments[0][\"container-image-reference\"] == \"ostree-unverified-image:containers-storage:localhost/fcos-derived\""

    # We'll test the "apply" automatic updates policy here
    systemctl stop rpm-ostreed
    cp /usr/etc/rpm-ostreed.conf /etc
    echo -e "[Daemon]\nAutomaticUpdatePolicy=apply" > /etc/rpm-ostreed.conf
    rpm-ostree reload

    # This should now prune the previous image
    rpm-ostree cleanup -pr
    ostree container image list --repo=/ostree/repo | tee imglist.txt
    assert_streq "$(wc -l < imglist.txt)" 1

    # Now revert back to the base image, but keep our layered package foo
    echo $(ostree refs ostree/container/blob | wc -l) > /etc/previous-layers
    rpm-ostree rebase ostree-unverified-image:containers-storage:localhost/fcos
    /tmp/autopkgtest-reboot 4
    ;;
  4) 
    # This should carry over
    rpm -q foo
    # But the other custom base image stuff should not
    for p in bar testdaemon; do
      if rpm -q $p 2>/dev/null; then
        fatal "found $p"
      fi
    done
    rpmostree_assert_status ".deployments[0][\"container-image-reference\"] == \"ostree-unverified-image:containers-storage:localhost/fcos\""
    rpm-ostree cleanup -r
    previous_layers=$(cat /etc/previous-layers)
    new_layers=$(ostree refs ostree/container/blob | wc -l)
    test $new_layers -lt $previous_layers
    ;;
  *) echo "unexpected mark: ${AUTOPKGTEST_REBOOT_MARK}"; exit 1;;
esac
